package ro.ubbcluj.cs.damate.persistence.entities;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import static javax.persistence.CascadeType.*;
import static javax.persistence.FetchType.LAZY;

/**
 * @author Lóránd Fazakas (lorand)
 *         Date: 4/22/12
 *         Time: 1:13 AM
 */
@Table(name = "user", catalog = "damate")
@Entity
public class User {

    private String username;

    @Column(name = "username", nullable = false, insertable = true, updatable = false, length = 30, precision = 0)
    @Id
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    private String password;

    @Column(name = "password", nullable = false, insertable = true, updatable = true, length = 40, precision = 0)
    @Basic
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String firstname;

    @Column(name = "firstname", nullable = false, insertable = true, updatable = true, length = 45, precision = 0)
    @Basic
    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    private String lastname;

    @Column(name = "lastname", nullable = false, insertable = true, updatable = true, length = 45, precision = 0)
    @Basic
    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    private boolean sex;

    @Column(name = "sex", nullable = false, insertable = true, updatable = true, length = 0, precision = 0)
    @Basic
    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    private Integer age;

    @Column(name = "age", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
    @Basic
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    private String email;

    @Column(name = "email", nullable = false, insertable = true, updatable = true, length = 200, precision = 0)
    @Basic
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    private boolean state;

    @Column(name = "state", nullable = false, insertable = true, updatable = true, length = 0, precision = 0)
    @Basic
    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }

    private Date registrationDate;

    @Column(name = "registrationDate", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
    @Basic
    public Date getRegistrationDate() {
        return registrationDate;
    }

    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }

    private Timestamp lastActive;

    @Column(name = "lastActive", nullable = false, insertable = true, updatable = true, length = 19, precision = 0)
    @Basic
    public Timestamp getLastActive() {
        return lastActive;
    }

    public void setLastActive(Timestamp lastActive) {
        this.lastActive = lastActive;
    }

    private Group group;

    @ManyToOne(fetch = LAZY, cascade = REFRESH)
    @JoinColumn(name = "userGroup")
    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

    private List<Team> managedTeams;

    @OneToMany(fetch = LAZY, cascade = REFRESH, mappedBy = "teamLeader")
    @OrderBy("teamName asc")
    public List<Team> getManagedTeams() {
        return managedTeams;
    }

    public void setManagedTeams(List<Team> managedTeams) {
        this.managedTeams = managedTeams;
    }

    private List<Team> assignedTeams;

    @ManyToMany(fetch = LAZY, mappedBy = "members", cascade = REFRESH)
    @OrderBy("teamName asc")
    public List<Team> getAssignedTeams() {
        return assignedTeams;
    }

    public void setAssignedTeams(List<Team> assignedTeams) {
        this.assignedTeams = assignedTeams;
    }

    private List<Section> managedSections;

    @OneToMany(fetch = LAZY, cascade = REFRESH, mappedBy = "sectionLeader")
    @OrderBy("sectionName asc")
    public List<Section> getManagedSections() {
        return managedSections;
    }

    public void setManagedSections(List<Section> managedSections) {
        this.managedSections = managedSections;
    }

    private List<Section> assignedSections;

    @ManyToMany(fetch = LAZY, mappedBy = "sectionManagers", cascade = REFRESH)
    @OrderBy("sectionName asc")
    public List<Section> getAssignedSections() {
        return assignedSections;
    }

    public void setAssignedSections(List<Section> assignedSections) {
        this.assignedSections = assignedSections;
    }

    private List<Event> events;

    @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "relatedUser")
    public List<Event> getEvents() {
        return events;
    }

    public void setEvents(List<Event> events) {
        this.events = events;
    }

    private List<ObservedObject> observedResources;

    @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "owner")
    public List<ObservedObject> getObservedResources() {
        return observedResources;
    }

    public void setObservedResources(List<ObservedObject> observedResources) {
        this.observedResources = observedResources;
    }

    public void addObservedResource(ObservedObject observedResource) {
        List<ObservedObject> resources = getObservedResources();
        if (resources == null) {
            resources = new ArrayList<ObservedObject>();
        }
        resources.add(observedResource);
    }

    private List<Token> tokens;

    @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "user")
    public List<Token> getTokens() {
        return tokens;
    }

    public void setTokens(List<Token> tokens) {
        this.tokens = tokens;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User that = (User) o;

        if (sex != that.sex) return false;
        if (state != that.state) return false;
        if (age != null ? !age.equals(that.age) : that.age != null) return false;
        if (email != null ? !email.equals(that.email) : that.email != null) return false;
        if (firstname != null ? !firstname.equals(that.firstname) : that.firstname != null) return false;
        if (lastActive != null ? !lastActive.equals(that.lastActive) : that.lastActive != null) return false;
        if (lastname != null ? !lastname.equals(that.lastname) : that.lastname != null) return false;
        if (password != null ? !password.equals(that.password) : that.password != null) return false;
        if (registrationDate != null ? !registrationDate.equals(that.registrationDate) : that.registrationDate != null)
            return false;
        if (username != null ? !username.equals(that.username) : that.username != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = username != null ? username.hashCode() : 0;
        result = 31 * result + (password != null ? password.hashCode() : 0);
        result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
        result = 31 * result + (lastname != null ? lastname.hashCode() : 0);
        result = 31 * result + (sex ? 1 : 0);
        result = 31 * result + (age != null ? age.hashCode() : 0);
        result = 31 * result + (email != null ? email.hashCode() : 0);
        result = 31 * result + (state ? 1 : 0);
        result = 31 * result + (registrationDate != null ? registrationDate.hashCode() : 0);
        result = 31 * result + (lastActive != null ? lastActive.hashCode() : 0);
        return result;
    }
}
